<template>
  <van-field
    v-if="h5"
    v-show="designer || (item.options && !item.options.hidden)"
    v-model="fieldModel"
    type="text"
    :name="item.options && item.options.name"
    :label="item.options && item.options.label"
    :readonly="true"
    :placeholder="isDetail ? '' : item.options && item.options.placeholder"
    :border="false"
    :label-width="item.options?.labelPosition === 'top' ? '100%' : undefined"
    :label-align="(item.options && item.options.labelPosition) || undefined"
    :input-align="(item.options && item.options.inputAlign) || undefined"
    autocomplete="off"
  >
    <template v-if="append" #button>
      {{ append }}
    </template>
  </van-field>
  <widget-form-item
    v-else
    v-show="designer || (item.options && !item.options.hidden)"
    :designer="designer"
    :widget-list="widgetList"
    :item="item"
    :index="index"
    :show-message="!isDetail"
  >
    <el-input
      v-if="!isDetail"
      :key="item.options.type"
      v-model="fieldModel"
      type="text"
      :readonly="true"
      :placeholder="item.options && item.options.placeholder"
      :min="item.options && item.options.min"
      :max="item.options && item.options.max"
    >
      <template v-if="append" #append>{{ append }}</template>
    </el-input>
    <div v-else>
      {{ fieldModel }}
      <span v-if="append" style="padding-left: 8px">{{ append }}</span>
    </div>
  </widget-form-item>
</template>

<script>
import { ref, reactive, computed, watch } from 'vue'
import props from './props'
import field from './field'

export default {
  name: 'MComputedays',
  props,
  emits: ['update:modelValue'],
  setup(props, { emit }) {
    const append = computed(() => {
      if (props.item.options.append) {
        return props.item.options.append
      }
      return ''
    })

    /**
     * 计算请假时长
     * @param {Date} startDateTime 开始时间
     * @param {Date} endDateTime 结束时间
     * @param {Object} options 配置选项
     * @param {boolean} options.workdayMode 是否工作日模式
     * @param {string[]} options.holidays 法定节假日数组，格式如['2024-01-01']
     * @param {string[]} options.workdays 调休工作日数组，格式如['2024-02-11']
     * @param {Array} options.workTime 每日工作时间段，如[{ start: '09:00', end: '12:00' }, { start: '13:00', end: '18:00' }]
     * @param {boolean} options.returnHours 是否返回小时数（默认返回天数）
     * @returns {number} 请假天数（0.5的倍数）
     */
    function calculateLeaveDuration(
      startDateTime,
      endDateTime,
      { workdayMode, holidays = [], workdays = [], workTime = [], returnHours = false }
    ) {
      if (startDateTime > endDateTime) throw new Error('结束时间必须晚于开始时间')

      // 自然日计算
      if (!workdayMode) {
        const diffHours = (endDateTime - startDateTime) / (1000 * 60 * 60)
        if (returnHours) return diffHours // 返回小时数
        return roundToHalf(diffHours / 24) // 返回天数
      }

      // 工作日计算
      let totalHours = 0
      const current = new Date(startDateTime)
      current.setHours(0, 0, 0, 0) // 从开始日期的0点开始遍历

      while (current <= endDateTime) {
        if (isWorkday(current, holidays, workdays)) {
          const dayStart = new Date(current)
          const dayEnd = new Date(current)
          dayEnd.setDate(dayEnd.getDate() + 1)

          const effectiveStart = startDateTime > dayStart ? startDateTime : dayStart
          const effectiveEnd = endDateTime < dayEnd ? endDateTime : dayEnd

          totalHours += calculateDailyHours(effectiveStart, effectiveEnd, workTime)
        }
        current.setDate(current.getDate() + 1)
      }

      if (returnHours) return totalHours // 返回小时数
      return roundToHalf(totalHours / 8) // 返回天数
    }

    // 判断是否为工作日
    function isWorkday(date, holidays, workdays) {
      const dateStr = date.toISOString().split('T')[0]
      if (holidays.includes(dateStr)) return false

      const dayOfWeek = date.getDay()
      const isWeekend = dayOfWeek === 0 || dayOfWeek === 6
      return isWeekend ? workdays.includes(dateStr) : true
    }

    // 计算单日有效工时
    function calculateDailyHours(start, end, workTime) {
      let totalMs = 0
      const startMs = start.getTime()
      const endMs = end.getTime()

      workTime.forEach(({ start: s, end: e }) => {
        const [sHour, sMin] = s.split(':').map(Number)
        const [eHour, eMin] = e.split(':').map(Number)

        const workStart = new Date(start)
        workStart.setHours(sHour, sMin, 0, 0)
        const workEnd = new Date(start)
        workEnd.setHours(eHour, eMin, 0, 0)

        const overlapStart = Math.max(startMs, workStart.getTime())
        const overlapEnd = Math.min(endMs, workEnd.getTime())
        if (overlapStart < overlapEnd) totalMs += overlapEnd - overlapStart
      })

      return totalMs / (1000 * 60 * 60) // 转换为小时
    }

    // 四舍五入到0.5的倍数
    function roundToHalf(num) {
      return Math.round(num * 2) / 2
    }

    watch(
      () => props.formData,
      (data) => {
        const { selectStart, selectEnd, workdayMode, holidays, workdays, workTime, append } = props.item.options
        const returnHours = append === '小时'
        if (selectStart && selectEnd) {
          if (data[selectStart] && data[selectEnd]) {
            const start = new Date(data[selectStart].replace(/\s/, 'T'))
            const end = new Date(data[selectEnd].replace(/\s/, 'T'))
            if (start < end) {
              const value = calculateLeaveDuration(start, end, {
                workdayMode,
                holidays,
                workdays,
                workTime,
                returnHours
              })
              emit('update:modelValue', String(value))
            } else {
              emit('update:modelValue', '0')
            }
          }
        }
      },
      { deep: true }
    )

    return {
      append,
      ...field(props, emit)
    }
  }
}
</script>
